home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / rs0422.zip / LEVEL2 / AX25L2.C < prev    next >
C/C++ Source or Header  |  1990-10-24  |  23KB  |  766 lines

  1. /*  AX25 Level 2 interface  --  KE3Z 08/9/87  */
  2.  
  3. #include "buffer.h"
  4. #include "iface.h"
  5. #include "timer.h"
  6. #include "ax25.h"
  7. #include "ax25l2.h"
  8. #include "netuser.h"
  9. #include "data.h"
  10. #include "hdlctl.h"
  11.  
  12. struct axcb *links; /* Main should init this  = NULL; */
  13. int control;
  14. struct ax25_addr adr[9];
  15. unsigned char swpos;
  16. unsigned char numadr, numadrm;    /* Number of addresses (callsigns) */
  17.  
  18. extern unsigned char digi;
  19.  
  20. extern unsigned char node_addr[16];
  21. extern struct ax25_addr L3CALL[1], L3DIGI[1];
  22.  
  23. extern struct ax25_parms *l3parms;
  24. int l3_st_up(), l2_window();
  25. void level3(), NULLFCN();
  26.  
  27. /*  lookup_axcb -- searches through the list of axcbs for a match to the
  28.  *  input parameters and returns a pointer to the first matching axcb.
  29.  *  returns NULL if no match found.
  30.  */
  31. struct axcb *
  32. lookup_axcb(laddr, raddrx, iface, alenx)
  33. struct ax25_addr *laddr;    /* Local address to match */
  34. struct ax25_addr raddrx[];    /* Remote address to match */
  35. struct interface *iface;    /* Interface to match */
  36. int alenx;
  37. {
  38.     register struct axcb *axcb;
  39.     int callcmp();
  40.     static int i, j;
  41.     static struct ax25_addr *raddr;    /* Remote address to match */
  42.     static int alen;
  43.  
  44.     alen=alenx;
  45.     if ((raddr=raddrx) == NULL || laddr == NULL) return NULL;    
  46.     for (axcb = links; axcb != NULL; axcb = axcb->next) {
  47.     if (callcmp(laddr, &axcb->myaddr) &&    /* MYCALL match */
  48.        (iface == axcb->iface) &&        /* Interface matches */
  49.        (axcb->alen == alen) &&        /* Path same length */ 
  50.        (callcmp(raddr,axcb->path)))     /* Src matches */ {
  51.         j=alen;
  52.         for (i=1;i<alen;i++) /* Check path */ {
  53.             j--;
  54.             if ((((raddr[j].ssid & (SSID | REPEATED)) ^ REPEATED)
  55.                 != (axcb->path[i].ssid & (SSID | REPEATED)))
  56.                 || !callcmp(&raddr[alen-i],&axcb->path[i]))
  57.                             goto no_match;
  58.             /* The above insures the REPEATED bits are
  59.                    right (the path in axcb has them toggled) */
  60.         }
  61.         return axcb;
  62.         }
  63.     no_match: continue;
  64.     }
  65.     return NULL;
  66. }
  67.  
  68. /* ax25l2 -- handler of received AX.25 frames. */
  69. struct datastr *
  70. ax25l2(ifacex, bpx)        /* If it returns the frame then free it */
  71. struct interface *ifacex;    /* Interface frame was received on */
  72. struct datastr *bpx;        /* Received frame */
  73. {
  74.     static struct interface *iface;    /* Interface frame was received on */
  75.     static struct datastr *bp;    /* Received frame */
  76.     register struct axcb *axcb;
  77.     static char rxversion;
  78.     static unsigned char *chr, *chx;
  79.     static unsigned char iscmd;
  80.     static int ctl;
  81.     static struct change *ch;
  82.     static struct change *state_tables[3][2][2] = {
  83.         { {rr_resp, rr_respf}, {rr_cmd, rr_cmdp} },
  84.         { {rnr_resp, rnr_respf}, {rnr_cmd, rnr_cmdp} },
  85.         { {rr_resp, rr_respf}, {rr_resp, rr_cmdp} }
  86.     };
  87.  
  88.     static struct change *state_tableu[6] =
  89.         { NULL, disc_cmd, ua_resp, frmr_resp, dm_resp, sabm_cmd };
  90.  
  91.     struct datastr *proci(), *setaddr();
  92.     int callcmp();
  93.     struct axcb *l2conreq();
  94.  
  95.     iface=ifacex;
  96.     bp=bpx;
  97.     iscmd=0;
  98.     ch=NULL;
  99.  
  100.     /* Save Buffer start address incase this is a digipeat request */
  101.     chr = bp->rdata;
  102.  
  103.     /* Move the address field into local storage */
  104.     digi=0;
  105.     if ((numadr=get_addr(bp, adr, FALSE)) == 0) return NULL;
  106.  
  107.     control = *bp->rdata;
  108.     ctl = decode_ctl(control);
  109.  
  110.     /* Restore the buffer start address so we can return a whole frame
  111.         if we can't handle it */
  112.     chx = bp->rdata;
  113.     bp->rdata = chr;
  114.  
  115.     /* Check for valid address length, Ignore UI's and wrong PID */
  116.  
  117.     if ((numadr > 7) || (numadr < 2)) return bp;
  118.  
  119.     if (numadr == 3) {
  120.         if (digi) /* Not repeated yet */ {
  121.             if (callcmp(&adr[2],&L3DIGI[0])) {
  122.                 (*iface->send)(iface,bp);
  123.                 return NULL;
  124.             }
  125.             else return bp; /* Not for me */
  126.         }
  127.     }
  128.  
  129.     swpos = 0;
  130.     if (ctl == ctl_UI) return bp;            /* Ignore UI's */
  131.     if (callcmp(&adr[0],&L3CALL[0])) swpos = 1;
  132.     if (callcmp(&adr[1],&L3CALL[0])) return bp;    /* I sent it */
  133.     if (digi) {
  134.         if (callcmp(&adr[digi],&L3CALL[0]) ||
  135.             callcmp(&adr[digi],&L3DIGI[0])) swpos = digi+1;
  136.     }
  137.  
  138.     numadrm = numadr-1;
  139.     if ((axcb=lookup_axcb(&adr[0],&adr[1],iface,numadrm)) == NULL) {
  140.         if ( !swpos ||    (ctl == ctl_DM) ) return bp;
  141.         if (ctl == ctl_SABM) axcb=l2conreq(iface);
  142.         if (axcb == EOF) return bp;    /* To us, but ignore */
  143.         if (axcb == NULL) {
  144.         /* We get here if there is no link or against our rules */
  145.             axcb=new_link();
  146.             axcb->iface = iface;
  147.             callcpy(&axcb->myaddr, &adr[0]);
  148.             setpath(axcb, &adr[1], 1, numadrm);
  149.             (*iface->send)(iface,setaddr(axcb,DM,0) );
  150.             free(axcb);
  151.             return bp;
  152.         }
  153.     }
  154.  
  155.     bp->rdata = chx;    /* Restore buffer to the ctl field */
  156.     (void)bgetch(&bp);    /* Fetch the control field */
  157.  
  158.     /* Determine the protocol version of the received frame */
  159.     if ((adr[0].ssid ^ adr[1].ssid) & C)
  160.         rxversion = V2;
  161.     else
  162.         rxversion = V1;
  163.  
  164.     /* Determine if received frame is command or response */
  165.     if ((adr[0].ssid & C) && !(adr[1].ssid & C)) iscmd = 1;
  166.  
  167.     /* Reject any non-I frame with an I field except FRMR type */
  168.     if (ctl != ctl_I && ctl != ctl_FRMR && buflen(bp) != 0) {
  169.         frmr(axcb, W+X, control, iscmd);
  170.         return bp;
  171.     }
  172.     /* Process the frame based on control field type */
  173.  
  174.     if (ctl>0) {
  175.         if (ctl<4) ch = state_tables[ctl-1]
  176.                     [ ( iscmd ? 1 : 0) ]
  177.                     [ ( ctl_PF ? 1 : 0)];
  178.         else ch = state_tableu[ctl-4];
  179.     }
  180.     else if (ctl == -1) ctl = ctl_SABM+1;
  181.  
  182.     if (ctl <= ctl_REJ) {
  183.                 /* S frames: process the N(R), then respond
  184.                     via state table nothing tricky here */
  185.          axcb->window=l2_window(axcb->parms);
  186.         procnr(axcb, control, iscmd);
  187.  
  188.                 /* I frames: process the receive-sequence  */
  189.                 /* number N(R), followed by the I field. */
  190.         if (ctl == ctl_I) {
  191.             bp = proci(axcb, bp, control, iscmd);
  192.         }
  193.     }
  194.     else if (ctl <= ctl_DM) {
  195.                 /* U frames: respond via state table except
  196.                     for SABM and UA, which require
  197.                     a little special handling. */
  198.         if (ctl == ctl_UA)
  199.             if (axcb->state == 2) /* Update the link version on connect */
  200.                 axcb->version = rxversion;
  201.     }
  202.     else if (ctl == ctl_SABM) {
  203.         axcb->iface = iface;
  204.         setpath(axcb, &adr[1], 1, numadrm); /* Reset Path */
  205.         link_reset(axcb); /* Reset the link */
  206.         axcb->version = rxversion; /* Update the link version */
  207.         idle_t1(axcb, 1); /* Start t3 running */
  208.         (void)(*axcb->s_upcall)(axcb,0,0);
  209.     }
  210.     else /* Reject bad control field */
  211.         frmr(axcb, W, control, iscmd);
  212.  
  213.     if (ch != NULL)    /* I frames handled elsewhere */
  214.         respond(axcb, ch, control, iscmd);
  215.  
  216.     return bp; /* Free the frame, will be NULL if proci accepted data */
  217. }
  218.  
  219. /* respond -- act on the received frame via the passed state table
  220.  */
  221. respond(axcb, ch, rctl, rcmd)
  222. register struct axcb *axcb;    /* Link */
  223. struct change *ch;    /* State table pointer */
  224. unsigned char rctl;    /* Received control field */
  225. char rcmd;        /* Received frame was a command */
  226. {
  227.     static int st, acts;
  228.     static int sctl;
  229.     static unsigned char pf;
  230.  
  231.     puthex2("respond",ch,"ctl",rctl);
  232.  
  233.     pf=0;
  234.     st = axcb->state -1;        /* State-table index */
  235.     acts = ch[st].acts;        /* Get action flags */
  236.     /* Reset the t1 timer and restore the retry count (n2) if specified */
  237.     if (acts & RSTT1) idle_t1(axcb, 1);
  238.     /* Here if a resulting frame is to be transmitted */
  239.     sctl=ch[st].ctl;
  240.     if (sctl == 255) sctl= -1; /* Just incase chars are unsigned/tm */
  241.     if (sctl != -1) {
  242.     /* FRMR handled specially */
  243.         if (sctl == FRMR) {
  244.             frmr(axcb, -1, 0, 0);
  245.             return;
  246.         }
  247.     /* If I frame transmission specified, check that there is data on
  248.      * the transmit queue.  If not, change to S frame or nothing, based
  249.      * on the state of the RESPOND action flag.
  250.      */
  251.         if (!(sctl & 1))
  252.             if (axcb->iqueue == NULL)
  253. #if 0
  254.                 if (acts & RESPOND)
  255.                     sctl = (axcb->flags & BUSY) ? RNR : RR;
  256.                 else
  257.                     sctl = -1;
  258. #endif
  259.                 sctl = ((acts & RESPOND) ?
  260.                     ((axcb->flags & BUSY) ? RNR : RR) : -1);
  261.  
  262.     /* Set P/F bit from received frame or action flag */
  263.         if (axcb->version == V1 || rcmd) pf = rctl & PF;
  264.         pf |= acts & PF;
  265.     }
  266.     /* Send the frame, change the state and all that dreck */
  267.     actionl2(axcb, ch[st].newstate, sctl, pf, acts);
  268. }
  269.  
  270. /* setpath -- update axcb path from received address field */
  271. setpath(axcb, addr, swapdigi, alenx)
  272. register struct axcb *axcb;        /* Link to update */
  273. struct ax25_addr *addr;        /* received address field */
  274. char swapdigi;            /* 1 if digis need to be reverse order */
  275. int alenx;
  276. {
  277.     static int i, j, alen;
  278.  
  279.     alen = alenx;
  280.     /* Store path in axcb */
  281.     axcb->alen = alen;
  282.     if (!alen) return;
  283.  
  284.     /* Clear all address-extension bits, and set the last */
  285.     for (i = 0; i < alen; i++) {
  286.         j=i;
  287.         if (swapdigi && i>0) j=alen-i;
  288.         bcopy(addr[i].call, axcb->path[j].call, ALEN);
  289.         axcb->path[j].ssid = (addr[i].ssid & ~E );
  290.         if (i>0) axcb->path[j].ssid ^= REPEATED; /* Toggle Repeated bit*/
  291.     }
  292.     if (i>1) axcb->path[alen-1].ssid |= E;    /* Set the last extension bit */
  293.     else axcb->myaddr.ssid |= E;
  294. }
  295.  
  296. /* link_reset -- stops the timers, clears the flags and resets the
  297.  * sequence numbers for the link.
  298.  */
  299. link_reset(axcb)
  300. register struct axcb *axcb;    /* Link */
  301. {
  302.     axcb->vs = axcb->ns = axcb->nr = 0;
  303.     axcb->flags &= ~INVNS;
  304.     kill(axcb->t1);        /* Kill all timers */
  305.     kill(axcb->t2);
  306.     kill(axcb->t3);
  307.     kill(axcb->t20);
  308.     free_queue(&axcb->iqueue); /* Throw out any outstanding tx or rx data */
  309.     free_pkt(axcb->rcvq);
  310.     axcb->icnt = 0;
  311.     axcb->rcvcnt = 0;
  312. }
  313.  
  314. /* axconnect -- initiate connect attempt on link (also known as a
  315.  * "local start command" in the protocol spec). Returns 1 if OK, else 0
  316.  */
  317. axconnect(axcb)
  318. register struct axcb *axcb;
  319. {
  320.     if (axcb->alen == 0) return 0;    /* No path set! */
  321.  
  322.     axcb->n2cnt = (axcb->parms->retry >> 1);
  323.     if (axcb->n2cnt == 0) axcb->n2cnt = 1;
  324.     /* Send a SABM command, transition to state 2, start t1 */
  325.     actionl2(axcb, 2, SABM, PF, CMD+RSTT1+SETT1);
  326.     return 1;
  327. }
  328.  
  329. void
  330. setcalls(p,calls)
  331. struct datastr *p;
  332. register struct ax25_addr *calls;
  333. {
  334.     static int j;
  335.  
  336.     for (j=0;j<ALEN;j++) {
  337.         bappch(p,calls->call[j]);
  338.     }
  339.     bappch(p,calls->ssid);
  340. }
  341.  
  342. struct datastr *
  343. setaddr(axcb,ctl,size)
  344. register struct axcb *axcb;
  345. int ctl,size;
  346. {
  347.     static struct datastr *p;
  348.     static char i;
  349.  
  350.     /* Room for address and control and extra space needed by caller */
  351.     p=new_buffer( 1 + size + (axcb->alen+1) * AXALEN);
  352.     if (p==NULL) return NULL;
  353.  
  354.     setcalls(p,&axcb->path[0]);
  355.     setcalls(p,&axcb->myaddr);
  356.     for (i=1;i<axcb->alen;i++) setcalls(p,&axcb->path[i]);
  357.  
  358.     bappch(p,ctl);
  359.     return p;
  360. }
  361.  
  362. /* actionl2 -- takes action on the link.
  363.  */
  364. actionl2(axcb, newstatex, sctlx, pf, acts)
  365. register struct axcb *axcb;    /* Link    */
  366. char newstatex;        /* New state, or 0 if no change    */
  367. int sctlx;        /* Control field to send */
  368. char pf;            /* P/F bit needed */
  369. char acts;        /* Action flags    */
  370. {
  371.     static char oldstate, newstate;
  372.     static int sctl;
  373.  
  374.     puthex2("actionl2",sctlx,"newst",newstate);
  375.  
  376.     newstate=newstatex;
  377.     oldstate = axcb->state;        /* Save old state */
  378.     /* Reset link if connecting */
  379.     if ((sctl=sctlx) == SABM) {
  380.         link_reset(axcb);
  381.         axcb->version = axcb->parms->version;    /* Reset version */
  382.     }
  383.     /* State transition.  Set new state, then call state-change upcall if
  384.      * going into an information-transfer state (i.e. state > 4) from a
  385.      * setup state (i.e. state < 5)
  386.      */
  387.     if (newstate != 0) {
  388.         axcb->state = newstate;
  389.         if (oldstate < 5 && newstate > 4) {
  390.     /* Return busy indication if no upcall vector or upcall function
  391.      * returns error indication
  392.      */
  393.             if ( !(*axcb->s_upcall)(axcb, oldstate, newstate)) {
  394.                 sctl = DM;
  395.                 newstate = axcb->state = 1;
  396.             } else {
  397.     /* Now that state-change upcall has been made, perform transmit upcall
  398.      */
  399.                 (*axcb->t_upcall)(axcb);
  400.             }
  401.         }
  402.     }
  403.  
  404.     /* Transmission handler.  Set C bits for command/response/none (V1) */
  405.  
  406.     if (sctl != -1 && !axcb->t2) /* MAY BE BUG 3/20 from 303 */ {
  407.         axcb->myaddr.ssid &= ~C;
  408.         axcb->path[0].ssid &= ~C;
  409.         if (axcb->version >= V2)
  410.             if (acts & CMD)
  411.                 axcb->path[0].ssid |= C;
  412.             else
  413.                 axcb->myaddr.ssid |= C;
  414.  
  415.     /* If I frame, call the sending function and quit */
  416.         if (!(sctl & 1) && (axcb->iqueue != NULL)) {
  417.             sendi(axcb);
  418.             return;
  419.         }
  420.     /* If S frame, merge receive-sequence variable into control field */
  421.  
  422.         if ((sctl & 3) == S) sctl |= (axcb->nr << 5);
  423.         if (pf)    sctl |= PF;    /* Put P/F bit in */
  424.  
  425.     /* Call interface driver to transmit the frame */
  426.  
  427.         (*axcb->iface->send)(axcb->iface,setaddr(axcb,sctl,0));
  428.     }
  429.     /* If specified by action flag, start/restart t1 running */
  430.     if (acts & SETT1) recovery(axcb);
  431.     else sendi(axcb);        /* Send I frames if possible */
  432.  
  433.     /* If going disconnected, clear the link */
  434.     if (axcb->state < 2) {
  435.         link_reset(axcb);
  436.         axcb->flags = 0;
  437.     /* Inform state-change upcall function of disconnect */
  438.         if (oldstate > 1) (*axcb->s_upcall)(axcb, oldstate, newstate);
  439.     }
  440. }
  441.  
  442. /* sendi - sends I frame(s).  Sends up to axcb->maxframe frames from
  443.  * the transmit queue
  444.  */
  445.  
  446. sendi(axcb)
  447. register struct axcb *axcb;    /* Link */
  448. {
  449.     static struct datastr *bp;
  450.     static struct datastr *dp;
  451.     static int i;
  452.     static char ctl;
  453.  
  454.     if (axcb->iqueue == NULL) return;    /* Nothing to send */
  455.     if ((axcb->t1 != NULL) || (axcb->t2 != NULL) || (axcb->state<5)) return;
  456.     /* Can't send I frames if t1 or t2 running or not connected */
  457.  
  458.     axcb->vs = axcb->ns;        /* Init send variable */
  459.     bp = axcb->iqueue;        /* Point to top of queue */
  460.     axcb->myaddr.ssid &= ~C; /* I frame is never a response */
  461.     if (axcb->version == V1)
  462.         axcb->path[0].ssid &= ~C;
  463.     else                /* Make it a command */
  464.         axcb->path[0].ssid |= C;
  465.     /* Frame-send loop */
  466.     for (i = 0; i < axcb->parms->maxframe; i++, bp = bp->next) {
  467.         puthex2("txfrm",axcb->parms->maxframe,"",bp);
  468.         if (bp == NULL)    break;        /* Quit at end of queue */
  469.         ctl=(axcb->nr << 5) | (axcb->vs << 1); /* Form control field */
  470.     /* Make a copy of the data, we might have to send it again */
  471.         dp = dup_pkt(bp);
  472.         if ((axcb->iface->send == NULL)    || !dp) break;    /* Can't Send */
  473.         dp= binsert( setaddr(axcb,ctl,0), dp );
  474.         (*axcb->iface->send)(axcb->iface,dp);
  475.         axcb->vs = (axcb->vs + 1) & 7;    /* Increment send variable */
  476.     }
  477.     recovery(axcb);        /* Start the t1 timer */
  478. }
  479.  
  480. /* procnr -- process the N(R) value of a received I or S frame */
  481. procnr(axcb, control, iscmd)
  482. register struct axcb *axcb;    /* Link    */
  483. int control;            /* Received control field */
  484. char iscmd;            /* 1 if received frame is a command */
  485. {
  486.     static char rs, top, acked;
  487.     static struct datastr *bp;
  488.  
  489.     acked=0;
  490.     /* Don't bother if we are'nt connected */
  491.     if (axcb->state < 5)
  492.         return;
  493.     /* Break the sequence number out of the control field */
  494.     rs = ctl_NR;    /* (control >> 5) & 7; */
  495.     /* Determine the proper highest and lowest acceptible sequence values
  496.      * If the N(S) value (lowest outstanding frame number) is greater than
  497.      * or equal to V(S) (highest outstanding frame number), adjust V(S) to
  498.      * a value greater than N(S) by adding 8 to it and to R(S).  (This
  499.      * happens when the modulo-8 sequence number "rolls over" to 0 during
  500.      * transmission.)
  501.      */
  502.     if (axcb->vs >= axcb->ns)
  503.         top = axcb->vs;
  504.     else {
  505.         top = axcb->vs + 8;
  506.         if (rs < axcb->ns)
  507.             rs += 8;
  508.     }
  509.     /* If R(S) isn't within the acceptible range, reject the frame */
  510.     if (rs < axcb->ns || rs > top) {
  511.         frmr(axcb, Z, control, iscmd);
  512.         return;
  513.     }
  514.     /* For each acknowledged frame, increment N(S), yank the acked frame
  515.      * off the tx queue, and reduce the queue data count.
  516.      */
  517.     while (rs > axcb->ns) {
  518.         axcb->ns++;
  519.         if (axcb->iqueue != NULL) {
  520.             bp = axcb->iqueue;
  521.             axcb->icnt -= buflen(bp);
  522.             axcb->iqueue = bp->next;
  523.             free_pkt(bp);
  524.         }
  525.     /* If a frame (or frames) is being acked, perform state-change stuff */
  526.         acked = 1;
  527.     }
  528.     /* Normalize N(S) modulo 8 */
  529.     axcb->ns &= 7;
  530.     /* If frames were acked and the tx window is open, notify the transmit
  531.      * upcall handler
  532.      */
  533.      if (acked || axcb->window > axcb->icnt) {
  534.         respond(axcb, (axcb->version == V1) ? val_nsv1 : val_ns, 0, 0);
  535.         (*axcb->t_upcall)(axcb);
  536.     }
  537. }
  538.  
  539. /* proci -- process the send-sequence number and I field of received
  540.  * frames
  541.  */
  542. struct datastr *
  543. proci(axcb, bpx, controlx, iscmd)
  544. register struct axcb *axcb;    /* Link */
  545. struct datastr *bpx;    /* Received frame */
  546. int controlx;        /* Received control field */
  547. char iscmd;        /* 1 if received frame was a command */
  548. {
  549.     static int pid, c;
  550.     static int control;
  551.     static char vs;
  552.     static struct datastr *bp1, *bp;
  553.     void t2_timeout();
  554.  
  555.     bp=bpx;
  556.     control=controlx;
  557.  
  558.     /* Don't bother if not connected */
  559.     if (axcb->state < 5) return bp;
  560.  
  561. #if 0
  562.     /* If I field is too big, reject the frame */
  563.     /* allow upto 4 extra bytes, PID and a trim 3 bytes for X.25 level 3 */
  564.     if (buflen(bp) > axcb->parms->framesize+4) {
  565.         frmr(axcb, Y, control, iscmd);    /* Ham Devices don't do this */
  566.         return bp;
  567.     }
  568. #endif
  569.  
  570.     /* Ignore received frames if we are busy (rx queue full) */
  571.     if (!(axcb->flags & BUSY)) {
  572.     /* Get the PID field */
  573.         if ( (pid=bgetch(&bp)) == -1)
  574.             frmr(axcb, W+Y, control, iscmd);
  575.     /* Break out the N(S) value and reset the "invalid N(S)" flag */
  576.         vs = ctl_NS;    /* (control >> 1) & 7; */
  577.         axcb->flags &= ~INVNS;
  578.     /* If this frame is not the expected one, set "invalid N(S)" */
  579.         if (vs != axcb->nr)
  580.             axcb->flags |= INVNS;
  581.     /* Save control field for delayed response */
  582.         axcb->rctl = control;
  583.     /* If this is expected frame, accept it */
  584.         if (vs == axcb->nr) {
  585.             axcb->rpid = pid; /* Update received PID */
  586.             axcb->nr = (axcb->nr + 1) & 7;    /* Increment our N(R) */
  587.             if ((c=buflen(bp)) > 0) { /* Process data in frame */
  588.                 bp1 = axcb->rcvq;
  589.                 /* Update receive queue count */
  590.                 axcb->rcvcnt += c;
  591.                 /* Update window Size based on free memory */
  592.                 axcb->window=l2_window(axcb->parms);
  593.     /* If receive window is now closed, perform go-busy routine */
  594.                 if (axcb->rcvcnt >= axcb->window) {
  595.                     axcb->flags |= BUSY;
  596.                     c = go_busy[axcb->state-1].newstate;
  597.                         /* Enter busy state */
  598.                     if (c != 0)
  599.                         axcb->state = c;
  600.                 }
  601. /* this may be converting frames in to a data stream, should be done in the
  602.    user module not a level 2 function!!! [append, next line] w2vy 10/86 */
  603.                 axcb->rcvq=binsert(axcb->rcvq, bp); 
  604.                 /* Put data on the rx queue */
  605.                 bp = NULL; /* Buffer isn't ours any more */
  606.             /* Always pass a revd frame to the upper layer w2vy */
  607.                 (*axcb->r_upcall)(axcb);
  608.             }
  609.             reset_t3(axcb);    /* Link activity; reset t3 */
  610.         }
  611.     }
  612.     /* If delayed-response is in effect, start t2 timer running */
  613. /*    kill(axcb->t2);    /* Incase it was running */
  614.     queue(&axcb->t2,t2_timeout,axcb->parms->resptime,axcb);
  615.  
  616.     return bp;
  617. }
  618. /* l2_window - Return what window size should be based on how much
  619. /* memory the switch has left, max size is maxframe*framesize */
  620. int
  621. l2_window(parms)
  622. register struct ax25_parms *parms;
  623. {
  624.     static int i;
  625.  
  626.     i=parms->maxframe * parms->framesize;
  627.     switch (spclev()) {
  628.         case FINE: return i;        /* Whole window */
  629.         case LIMITED: return (i>>1);    /* Only 1/2 */
  630.         case CRITICAL: return (0);    /* Nothing! */
  631.     }
  632. }
  633.  
  634. /* frmr -- reject bad received frame
  635.  * "errtyp" should be -1 to repeat the previous FRMR frame
  636.  */
  637. frmr(axcb, errtyp, control, iscmd)
  638. register struct axcb *axcb;    /* Link */
  639. char errtyp;        /* Error type for FRMR I field */
  640. char control;        /* Received control field */
  641. char iscmd;        /* 1 if received frame is command */
  642. {
  643.     static struct datastr *bp;
  644. /*    static char info[3]; */
  645.     static char *ch;
  646.     static char newstate;
  647.  
  648.     ch = axcb->info;
  649.     newstate=0;
  650.     if (errtyp != -1) {        /* Form new FRMR I field */
  651.         newstate = 3;            /* Go to frame reject state */
  652.     /* Form FRMR I field */
  653.         *ch++ = errtyp;
  654.         *ch = 0;
  655.         if (iscmd) *ch |= PF;
  656.         *ch++ |= (axcb->nr << 5) + (axcb->ns << 1);
  657.         *ch = control;
  658.         ch = axcb->info;
  659.     }
  660.     /* Make an datastr of the FRMR data and send it */
  661.     bp = setaddr(axcb,FRMR,3);
  662.     bappch(bp,*ch++);
  663.     bappch(bp,*ch++);
  664.     bappch(bp,*ch);
  665.     (*axcb->iface->send)(axcb->iface,bp);
  666.     actionl2(axcb, newstate, -1, 0, 0);    /* Transition to FRMR state */
  667. }
  668.  
  669. /* t1_timeout -- t1 timer handler.  On timeout:
  670.  * 1) Start t3 timer if not V1 protocol
  671.  * 2) Decrement retry (N2) count if not 0
  672.  * 3) If N2 decremented to 0, respond via "N2 exceeded" state table,
  673.  *    otherwise, respond via "t1 expired" state table
  674.  */
  675. void
  676. t1_timeout(axcb)
  677. register struct axcb *axcb;    /* Link    */
  678. {
  679.     idle_t1(axcb, 0);
  680.     if (axcb->n2cnt)
  681.         if (--axcb->n2cnt == 0) {
  682.             respond(axcb, n2_exceeded, 0, 0);
  683.             return;
  684.         }
  685.     respond(axcb, (axcb->version == V1) ? t1_expv1 : t1_exp, 0, 0);
  686. }
  687.  
  688. /* t2_timeout -- t2 timer handler.  On timeout, if link "invalid N(S)
  689.  * received" flag is set, respond via "invalid N(S)" state table, otherwise
  690.  * respond via "i frame" state table.
  691.  */
  692. void
  693. t2_timeout(axcb)
  694. register struct axcb *axcb;    /* Link    */
  695. {
  696.     (*axcb->r_upcall)(axcb);
  697.     if (axcb->flags & INVNS)
  698.         respond(axcb,(axcb->version == V1) ? inv_nsv1 : inv_ns,
  699.                     axcb->rctl, axcb->rcmd);
  700.     else
  701.         respond(axcb, (axcb->rctl & PF) ? i_cmdp : i_cmd,
  702.                     axcb->rctl, axcb->rcmd);
  703. }
  704.  
  705. /* t3_timeout -- t3 timer handler.  On timeout, respond via "t3 expired"
  706.  * state table.
  707.  */
  708. void
  709. t3_timeout(axcb)
  710. register struct axcb *axcb;    /* Link    */
  711. {
  712.     if (axcb->version == V1) close_ax25(axcb); /* Disconnect this guy */
  713.     else respond(axcb, t3_exp, 0, 0);    /* Poll or give up */
  714. }
  715.  
  716. /* recovery -- initializes (starts) t1 timer and stops t3 timer.
  717.  * t1 timer period is calculated by:
  718.  * p = (2*n + 1) * f
  719.  * where p=period in seconds, n = number of digi addresses in the link
  720.  * path, and f=frack
  721.  */
  722. /* static .. what is a static function?? /tm */
  723. recovery(axcb)
  724. register struct axcb *axcb;    /* Link */
  725. {
  726.     static int i, j;
  727.  
  728.     kill(axcb->t3);
  729.     i=axcb->alen;
  730.     if (i>2) i -= 2;    /* Subtract off the switch call and address */
  731.  
  732.     j = axcb->parms->retry - axcb->n2cnt + 1;
  733.     i=(i + (j<axcb->n2cnt ? j : axcb->n2cnt)) * axcb->parms->frack + rnd(3);
  734. #if 0
  735.     i = ( 2 *(i-1) +1) * (axcb->parms->frack *
  736.         (axcb->parms->retry - axcb->n2cnt + 1)) + rnd(3);
  737. #endif
  738.  
  739.     queue(&axcb->t1,t1_timeout,i,axcb);
  740. }
  741.  
  742. /* idle_t1 -- stops the t1 timer, optionally resetting the retry (N2) count.
  743.  * starts the inactive link (t3) timer if the link isn't using V1 protocol
  744.  */
  745. idle_t1(axcb, reset)
  746. register struct axcb *axcb;    /* Link    */
  747. char reset;        /* 1 to reset retry count */
  748. {
  749.     kill(axcb->t1);
  750.     if (reset)
  751.         axcb->n2cnt = axcb->parms->retry;
  752.     reset_t3(axcb);
  753. }
  754.  
  755. /* reset_t3 - restart t3 (link activity occurred) */
  756. reset_t3(axcb)
  757. register struct axcb *axcb;    /* Link    */
  758. {
  759.     static int c;
  760.  
  761. /*    kill(axcb->t3); */
  762.     c = axcb->parms->check;
  763.     if (axcb->am_dce) c += 3;
  764.     queue(&axcb->t3,t3_timeout,c,axcb);
  765. }
  766.